package com.company.calendar.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.company.calendar.dto.CalendarDayDTO;
import com.company.calendar.dto.CalendarQueryDTO;
import com.company.calendar.entity.*;
import com.company.calendar.mapper.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 日历服务类
 * 
 * @author System
 * @since 1.0.0
 */
@Service
@RequiredArgsConstructor
@Slf4j
@Transactional(readOnly = true)
public class CalendarService {
    
    private final HolidayMapper holidayMapper;
    private final CustomDateMapper customDateMapper;
    private final WorkdayConfigMapper workdayConfigMapper;
    private final WorkdayRuleMapper workdayRuleMapper;
    private final HolidayTypeMapper holidayTypeMapper;
    private final DateTypeMapper dateTypeMapper;
    
    /**
     * 获取日历数据
     */
    public List<CalendarDayDTO> getCalendarData(CalendarQueryDTO queryDTO) {
        log.info("获取日历数据: 公司ID={}, 日期范围={} 到 {}", 
                queryDTO.getCompanyId(), queryDTO.getStartDate(), queryDTO.getEndDate());
        
        List<CalendarDayDTO> calendarDays = new ArrayList<>();
        LocalDate currentDate = queryDTO.getStartDate();
        
        // 获取工作日配置
        WorkdayConfig defaultConfig = workdayConfigMapper
                .findByCompanyIdAndIsDefaultTrueAndIsDeletedFalse(queryDTO.getCompanyId());
        
        Map<Integer, WorkdayRule> workdayRules = new HashMap<>();
        if (defaultConfig != null) {
            workdayRules = workdayRuleMapper.findByConfigId(defaultConfig.getId())
                    .stream()
                    .collect(Collectors.toMap(WorkdayRule::getDayOfWeek, rule -> rule));
        }
        
        // 获取节假日数据
        List<Holiday> holidays = holidayMapper.findByCompanyIdAndDateRange(
                queryDTO.getCompanyId(), queryDTO.getStartDate(), queryDTO.getEndDate());
        Map<LocalDate, Holiday> holidayMap = holidays.stream()
                .collect(Collectors.toMap(Holiday::getHolidayDate, holiday -> holiday));
        
        // 获取自定义日期数据
        List<CustomDate> customDates = customDateMapper.findByCompanyIdAndDateRange(
                queryDTO.getCompanyId(), queryDTO.getStartDate(), queryDTO.getEndDate());
        Map<LocalDate, CustomDate> customDateMap = customDates.stream()
                .collect(Collectors.toMap(CustomDate::getCustomDate, customDate -> customDate));
        
        // 获取节假日类型和日期类型信息
        Map<Long, HolidayType> holidayTypeMap = holidayTypeMapper.findByIsDeletedFalse()
                .stream()
                .collect(Collectors.toMap(HolidayType::getId, type -> type));
        
        LambdaQueryWrapper<DateType> dateTypeWrapper = new LambdaQueryWrapper<>();
        dateTypeWrapper.eq(DateType::getCompanyId, queryDTO.getCompanyId());
        Map<Long, DateType> dateTypeMap = dateTypeMapper.selectList(dateTypeWrapper)
                .stream()
                .collect(Collectors.toMap(DateType::getId, type -> type));
        
        // 生成日历数据
        while (!currentDate.isAfter(queryDTO.getEndDate())) {
            CalendarDayDTO calendarDay = new CalendarDayDTO();
            calendarDay.setDate(currentDate);
            
            // 检查是否为自定义日期
            if (customDateMap.containsKey(currentDate)) {
                CustomDate customDate = customDateMap.get(currentDate);
                DateType dateType = dateTypeMap.get(customDate.getTypeId());
                
                calendarDay.setIsCustomDate(true);
                calendarDay.setIsWorkday(dateType.getIsWorkday());
                calendarDay.setDayType("CUSTOM");
                calendarDay.setTypeName(dateType.getTypeName());
                calendarDay.setTypeCode(dateType.getTypeCode());
                calendarDay.setColor(dateType.getColor());
                calendarDay.setDescription(customDate.getDescription());
            }
            // 检查是否为节假日
            else if (holidayMap.containsKey(currentDate)) {
                Holiday holiday = holidayMap.get(currentDate);
                HolidayType holidayType = holidayTypeMap.get(holiday.getTypeId());
                
                calendarDay.setIsHoliday(true);
                calendarDay.setIsWorkday(holiday.getIsWorkday());
                calendarDay.setDayType("HOLIDAY");
                calendarDay.setTypeName(holiday.getHolidayName());
                calendarDay.setTypeCode(holidayType.getTypeCode());
                calendarDay.setColor(holidayType.getColor());
                calendarDay.setDescription(holiday.getDescription());
            }
            // 根据工作日规则判断
            else {
                DayOfWeek dayOfWeek = currentDate.getDayOfWeek();
                int dayOfWeekValue = dayOfWeek.getValue(); // 1=Monday, 7=Sunday
                
                WorkdayRule rule = workdayRules.get(dayOfWeekValue);
                if (rule != null) {
                    calendarDay.setIsWorkday(rule.getIsWorkday());
                    calendarDay.setDayType("WORKDAY");
                } else {
                    // 默认规则：周一到周五工作日，周六周日休息
                    calendarDay.setIsWorkday(dayOfWeekValue <= 5);
                    calendarDay.setDayType("WORKDAY");
                }
            }
            
            calendarDays.add(calendarDay);
            currentDate = currentDate.plusDays(1);
        }
        
        return calendarDays;
    }
    
    /**
     * 检查指定日期是否为工作日
     */
    public boolean isWorkday(Long companyId, LocalDate date) {
        log.info("检查日期是否为工作日: 公司ID={}, 日期={}", companyId, date);
        
        // 检查是否为自定义日期
        CustomDate customDate = customDateMapper
                .findByCompanyIdAndCustomDateAndIsDeletedFalse(companyId, date);
        if (customDate != null) {
            DateType dateType = dateTypeMapper.selectById(customDate.getTypeId());
            return dateType != null && dateType.getIsWorkday();
        }
        
        // 检查是否为节假日
        Holiday holiday = holidayMapper
                .findByCompanyIdAndHolidayDateAndIsDeletedFalse(companyId, date);
        if (holiday != null) {
            return holiday.getIsWorkday();
        }
        
        // 根据工作日规则判断
        WorkdayConfig defaultConfig = workdayConfigMapper
                .findByCompanyIdAndIsDefaultTrueAndIsDeletedFalse(companyId);
        
        if (defaultConfig != null) {
            DayOfWeek dayOfWeek = date.getDayOfWeek();
            int dayOfWeekValue = dayOfWeek.getValue();
            
            List<WorkdayRule> rules = workdayRuleMapper.findByConfigId(defaultConfig.getId());
            Optional<WorkdayRule> ruleOpt = rules.stream()
                    .filter(rule -> rule.getDayOfWeek().equals(dayOfWeekValue))
                    .findFirst();
            
            if (ruleOpt.isPresent()) {
                return ruleOpt.get().getIsWorkday();
            }
        }
        
        // 默认规则：周一到周五工作日，周六周日休息
        DayOfWeek dayOfWeek = date.getDayOfWeek();
        return dayOfWeek.getValue() <= 5;
    }
    
    /**
     * 获取指定日期的详细信息
     */
    public CalendarDayDTO getDayInfo(Long companyId, LocalDate date) {
        log.info("获取日期详细信息: 公司ID={}, 日期={}", companyId, date);
        
        CalendarQueryDTO queryDTO = new CalendarQueryDTO();
        queryDTO.setCompanyId(companyId);
        queryDTO.setStartDate(date);
        queryDTO.setEndDate(date);
        
        List<CalendarDayDTO> calendarDays = getCalendarData(queryDTO);
        return calendarDays.isEmpty() ? null : calendarDays.get(0);
    }
}


